package sporteam.web.client;

import java.util.ArrayList;
import java.util.Date;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Sporteam_web implements EntryPoint {
	private static VerticalPanel mainPanel = new VerticalPanel();
	private static HorizontalPanel topPanel = new HorizontalPanel();
	private static HorizontalPanel buttonsPanel = new HorizontalPanel();
	private static FormPanel infoFormPanel = new FormPanel();
	private static FlexTable infoFlexTable = new FlexTable();
	private static HorizontalPanel runsPanel = new HorizontalPanel();
	private static FlexTable runsTable = new FlexTable();
	private static HorizontalPanel friendsPanel = new HorizontalPanel();
	public static FlexTable friendsTable = new FlexTable();

	private static VerticalPanel userInfoPanel = new VerticalPanel();
	private static Image userImage = new Image();
	private static Label userNameLabel = new Label();

	private GetUserFromDBServiceAsync GetUserFromDBService = GWT
			.create(GetUserFromDBService.class);
	private GetUserTracksFromDBServiceAsync GetUserTracksFromDBService = GWT
			.create(GetUserTracksFromDBService.class);
	private GetSpecificTrackFromDBServiceAsync GetSpecificTrackFromDBService = GWT
			.create(GetSpecificTrackFromDBService.class);
	private GetFriendsListFromDBServiceAsync GetFriendsListFromDBService = GWT
			.create(GetFriendsListFromDBService.class);
	private GetActivitiesFromDBServiceAsync GetActivitiesFromDBService = GWT
			.create(GetActivitiesFromDBService.class);

	public static JavaScriptObject jso_trackMap;
	public static JavaScriptObject jso_map;
	public static JavaScriptObject jso_map2;

	public static ArrayList<Track> tracks;
	public static MiniUser miniUser;
	public static ArrayList<String> friends_list;
	public static ArrayList<Activity> activities;

	private String sites_url = "https://sporteamws.appspot.com/";

	@Override
	public void onModuleLoad() {

		// Assemble buttons Panel
		final Button tracksButton = new Button("Tracks");
		//Disable this button until tracks loads later
		tracksButton.setEnabled(false);
		buttonsPanel.add(tracksButton);
		//
		final Button friendsButton = new Button("Friends");
		//Disable this button until friends loads later
		friendsButton.setEnabled(false);
		buttonsPanel.add(friendsButton);
		//
		final Button competitionsButton = new Button("Competitions");
		//Disable this button until friends loads later
		competitionsButton.setEnabled(false);
		buttonsPanel.add(competitionsButton);
		//
		Button infoButton = new Button("Info");
		buttonsPanel.add(infoButton);
		//
		Button logoutButton = new Button("Logout");
		buttonsPanel.add(logoutButton);

		// Add style classes to all of the topPanel buttons
		tracksButton.setStyleName("header-button");
		friendsButton.setStyleName("header-button");
		infoButton.setStyleName("header-button");
		logoutButton.setStyleName("header-button");

		// Add style to the top panel
		topPanel.setSpacing(6);
		topPanel.addStyleName("topPanel");

		// Assemble top panel
		topPanel.add(buttonsPanel);

		// Add style ot userInfoPanel
		userInfoPanel.setStyleName("userInfoPanel");
		userInfoPanel
				.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

		// Assemble userInfoPanel
		userInfoPanel.add(userNameLabel);
		userInfoPanel.add(userImage);

		// Create table for runsTable
		CreateRunTableHeader(runsTable);

		// Add style to the elements in the runsTable
		runsTable.setCellPadding(6);

		// Add styles to elements in the stock list table. TODO
		runsTable.getRowFormatter().setStyleName(0, "runsTableHeader");
		runsTable.setStyleName("runsTable");

		// Add click listener to the runsTable
		runsTable.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				HTMLTable.Cell cell = runsTable.getCellForEvent(event);
				if (cell == null) {
					// Window.alert("cell is null");
				} else if (cell.getRowIndex() == 0) {
					// DO NOTHING !!!
				} else {
					String facebook_access_token = com.google.gwt.user.client.Window.Location
							.getParameter("access_token");
					AsyncCallback<ArrayList<GeoPtr>> trackCallback = new AsyncCallback<ArrayList<GeoPtr>>() {

						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onSuccess(ArrayList<GeoPtr> result) {
							jso_trackMap = initializeMap(result.get(0));
							showTrackOnMap(result);
						}
					};

					GetSpecificTrackFromDBService.getTrack(
							facebook_access_token, cell.getRowIndex() - 1,
							trackCallback); // track 0 is at row 1

				}

			}
		});

		ScrollPanel runsTableScrollPanel = new ScrollPanel();
		runsTableScrollPanel.add(runsTable);
		runsTable.setWidth("100%");
		runsTableScrollPanel.setSize("300px", "400px");
		runsTableScrollPanel.setStyleName("scrollPanel");
		runsTableScrollPanel.setAlwaysShowScrollBars(false);
		runsTableScrollPanel.setHorizontalScrollPosition(0);
		
		SimplePanel runsTableSimplePanel = new SimplePanel();
		runsTableSimplePanel.add(runsTableScrollPanel);
		// Assemble runsPanel
		runsPanel.add(runsTableSimplePanel);
		// runsPanel.add(new
		// HTMLPanel("<div id=\"map\" style=\"width:30%; height:40%;\" ></div>"));
		// runsPanel.add(new MapPanel("map"));
		// runsPanel.add(new MapPanel("map2"));

		// Assemble infoPanel
		buildInfoFlexTable();

		// Assemble infoFormPanel
		infoFormPanel.setAction("/updateUserInfo");
		infoFormPanel.setMethod(FormPanel.METHOD_GET);
		infoFormPanel.setWidget(infoFlexTable);

		
		//create simple panel to contain scrollable friendslist
		ScrollPanel friendsScrollPanel = new ScrollPanel();
		friendsScrollPanel.add(friendsTable);
		friendsTable.setWidth("100%");
		friendsScrollPanel.setSize("300px", "400px");
		friendsScrollPanel.setStyleName("scrollPanel");
		friendsScrollPanel.setAlwaysShowScrollBars(false);
			
		// Assemble friends Panel
		Label friendsPanelTitleLabel = new Label("Your SporTeam friends:");
		friendsPanel.add(friendsPanelTitleLabel);
		friendsPanel.add(friendsScrollPanel);
		
		//Add style to friendsTable
		friendsTable.setStyleName("friendsTable");
		friendsTable.setCellSpacing(10);
		
		

		// Assemble main panel
		// mainPanel.add(topPanel);

		// Associate the topPanel with the HTML
		RootPanel.get("topPanel").add(topPanel);
		RootPanel.get("topPanel").add(userInfoPanel);

		// Associate the Main panel with the HTML host page.
		RootPanel.get("userPage").add(mainPanel);

		// Get the user's Facebook Access Token from the address bar (GET
		// parameter)
		String facebook_access_token = com.google.gwt.user.client.Window.Location
				.getParameter("access_token");

		// Remote call to get the user's data from the server
		AsyncCallback<MiniUser> callback = new AsyncCallback<MiniUser>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO we're fucked - now what we do?.

			}

			@Override
			public void onSuccess(MiniUser result) {
				miniUser = result;
				// Modify the userPanel inner widgets to display user info
				updateUserInfo(result);
				updateInfoFlexTable(result);
			}
		};

		GetUserFromDBService.GetUser(facebook_access_token, callback);

		// Remote call to get the user's data from the server
		AsyncCallback<ArrayList<Track>> callbackTracks = new AsyncCallback<ArrayList<Track>>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onSuccess(ArrayList<Track> result) {
				tracks = result;
				updateRunsTable(result);
				tracksButton.setEnabled(true);
			}
		};

		GetUserTracksFromDBService.getTracks(facebook_access_token,
				callbackTracks);

		// Remote call to get the user's friends list from the server
		AsyncCallback<ArrayList<String>> callbackFriendsList = new AsyncCallback<ArrayList<String>>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onSuccess(ArrayList<String> result) {
				friends_list = result;
				updateFriendsFlexTable(result);
				friendsButton.setEnabled(true);
				competitionsButton.setEnabled(true);
			}
		};

		GetFriendsListFromDBService.getFriendsList(facebook_access_token,
				callbackFriendsList);

		AsyncCallback<ArrayList<Activity>> callbackActivities = new AsyncCallback<ArrayList<Activity>>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onSuccess(ArrayList<Activity> result) {
				activities = result;

			}
		};

		GetActivitiesFromDBService.getActivities(facebook_access_token,
				callbackActivities);

		// Buttons click handlers:
		// On click - first of all remove current displaying widget and display
		// the requested widget

		tracksButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				removeCurrentWidget();
				showMap();
				jso_trackMap = initializeMap("trackMap");
				displayWidget(runsPanel);
				placeMap();
			}
		});

		friendsButton.addClickHandler(getDefaultClickHandler(friendsPanel));

		competitionsButton.addClickHandler(getDefaultClickHandler(CompetitionWeb.createCompetitionDisplay()));
		
		infoButton.addClickHandler(getDefaultClickHandler(infoFormPanel));

		logoutButton.addClickHandler(new ClickHandler() {

			// Sign out of facebook and go back to the homepage - (sites_url)
			@Override
			public void onClick(ClickEvent event) {
				String access_token = Window.Location
						.getParameter("access_token");
				Window.Location
						.assign("https://www.facebook.com/logout.php?next="
								+ sites_url + "&access_token=" + access_token);
			}
		});

	}

	private void CreateRunTableHeader(FlexTable runFlexTable) {
		runFlexTable.setText(0, 0, "Date");
		runFlexTable.setText(0, 1, "Distance");
		runFlexTable.setText(0, 2, "Time");
		runFlexTable.setText(0, 3, "Calories");
	}

	public static ClickHandler getDefaultClickHandler(final Panel panel) {
		return new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				removeCurrentWidget();
				displayWidget(panel);
			}
		};
	}

	public static void updateFriendsFlexTable(ArrayList<String> friends_list) {
		int rowIndex = 0;
		
		for (String friend : friends_list) {


			friendsTable.setWidget(rowIndex, 0,
					getFriendInfoPanel(friend));
			friendsTable.setText(rowIndex, 1, friend.split(";")[1].trim());
			rowIndex++;
		}

	}

	public static Image getFriendInfoPanel(String friend) {
		final String friend_id = friend.split(";")[0].trim();
		final String friend_name = friend.split(";")[1].trim();

		Label friendNameLabel = new Label();
		friendNameLabel.setText(friend_name);

		String friendImageURL = "https://graph.facebook.com/" + friend_id
				+ "/picture?type=square";
		Image friendImage = new Image();
		friendImage.setUrl(friendImageURL);
		friendImage.addStyleName("friendImage");

		HorizontalPanel friendInfoPanel = new HorizontalPanel();
		friendInfoPanel.add(friendImage);
		friendInfoPanel.add(friendNameLabel);

		friendImage.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				Panel friendActivityPanel = createFriendActivityPanel(
						friend_id, friend_name);
				jso_map = initializeMap("map");
				jso_map2 = initializeMap("map2");

				removeCurrentWidget();
				displayWidget(friendActivityPanel);
			}
		});

		return friendImage;
	}

	protected static Panel createFriendActivityPanel(String friend_id,
			String friend_name) {

		FlexTable activityFriendFlexTable = new FlexTable();
		createActivityFriendHeader(activityFriendFlexTable);
		updateActivityTable(activityFriendFlexTable, friend_id);

		// Add style to activityFriendFlexTable
		activityFriendFlexTable.getRowFormatter().addStyleName(0,
				"runsTableHeader");
		activityFriendFlexTable.addStyleName("runsTable");

		activityFriendFlexTable.addClickHandler(FriendActivityUtil
				.friendActivityFlexTableClickHandler(activityFriendFlexTable));

		HorizontalPanel activityFriendPanel = new HorizontalPanel();
		activityFriendPanel.add(activityFriendFlexTable);
		return activityFriendPanel;
	}

	private static void createActivityFriendHeader(FlexTable activityFriendFlexTable) {
		activityFriendFlexTable.setText(0, 0, "My Date");
		activityFriendFlexTable.setText(0, 1, "My Distance");
		activityFriendFlexTable.setText(0, 2, "My Time");
		activityFriendFlexTable.setText(0, 3, "My Calories");
		activityFriendFlexTable.setText(0, 4, "  --  ");
		activityFriendFlexTable.setText(0, 5, "Date");
		activityFriendFlexTable.setText(0, 6, "Distance");
		activityFriendFlexTable.setText(0, 7, "Time");
		activityFriendFlexTable.setText(0, 8, "Calories");
	}

	private static void updateActivityTable(FlexTable activityFriendFlexTable,
			String friend_id) {
		int rowIndex = 1;
		if (activities != null) {
			for (Activity activity : activities) {
				// if this activity involves the friend
				if (activity.getReceiverID().equals(friend_id)
						|| activity.getSenderID().equals(friend_id)) {
					
					//if the activity is completed (both tracks exist)
					if (activity.getReceiverTrack() != null
							&& activity.getSenderTrack() != null) {
						addActivityToActivityFriendFlexTable(activityFriendFlexTable, activity, rowIndex);
						rowIndex++;
					}
				}
			}
		}
	}

	private static void addActivityToActivityFriendFlexTable(
			FlexTable activityFriendFlexTable, Activity activity, int rowIndex) {
		Track myTrack, friendsTrack;

		if (activity.isImTheSender(miniUser.getFacebook_id())) {
			myTrack = activity.getSenderTrack();
			friendsTrack = activity.getReceiverTrack();
		} else {
			myTrack = activity.getReceiverTrack();
			friendsTrack = activity.getSenderTrack();
		}
		activityFriendFlexTable.setText(rowIndex, 0, myTrack.getName());
		activityFriendFlexTable.setText(rowIndex, 1,
				translateDistance(myTrack.GetDistance()));
		activityFriendFlexTable.setText(rowIndex, 2,
				translateTrackTime(myTrack.GetTrackTime()));
		activityFriendFlexTable.setText(rowIndex, 3,
				Double.toString(myTrack.getCalories()));

		activityFriendFlexTable.setText(rowIndex, 5, friendsTrack.getName());
		activityFriendFlexTable.setText(rowIndex, 6,
				translateDistance(myTrack.GetDistance()));
		activityFriendFlexTable.setText(rowIndex, 7,
				translateTrackTime(myTrack.GetTrackTime()));
		activityFriendFlexTable.setText(rowIndex, 8,
				Double.toString(friendsTrack.getCalories()));

		// Add style to each row
		activityFriendFlexTable.getRowFormatter().setStyleName(rowIndex,
				"runsTableRow");
	}

	protected void updateInfoFlexTable(MiniUser miniUser) {
		TextBox ageBox = (TextBox) infoFlexTable.getWidget(0, 1);
		ageBox.setValue(String.valueOf(miniUser.getAge()));
		TextBox emailBox = (TextBox) infoFlexTable.getWidget(1, 1);
		if (miniUser.getEmail() != null)
			emailBox.setValue(miniUser.getEmail());
		TextBox weightBox = (TextBox) infoFlexTable.getWidget(2, 1);
		weightBox.setValue(String.valueOf(miniUser.getWeight()));
		ListBox genderBox = (ListBox) infoFlexTable.getWidget(3, 1);
		Label genderLabel = (Label) infoFlexTable.getWidget(3, 0);
		if (miniUser.getGender().equals("male")) {
			genderBox.setValue(0, "male");
			genderBox.setVisible(false);
			genderLabel.setVisible(false);
		} else if (miniUser.getGender().equals("female")) {
			genderBox.setValue(0, "female");
			genderBox.setVisible(false);
			genderLabel.setVisible(false);
		}

	}

	private void buildInfoFlexTable() {
		final TextBox ageBox = new TextBox();
		ageBox.setName("Age");
		infoFlexTable.setWidget(0, 0, new Label("Age: "));
		infoFlexTable.setWidget(0, 1, ageBox);

		final TextBox emailBox = new TextBox();
		emailBox.setName("Email");
		infoFlexTable.setWidget(1, 0, new Label("Email: "));
		infoFlexTable.setWidget(1, 1, emailBox);

		final TextBox weightBox = new TextBox();
		weightBox.setName("Weight");
		infoFlexTable.setWidget(2, 0, new Label("Weight: "));
		infoFlexTable.setWidget(2, 1, weightBox);

		final ListBox genderBox = new ListBox();
		genderBox.setName("Gender");
		genderBox.addItem("Male", "male");
		genderBox.addItem("Female", "female");
		infoFlexTable.setWidget(3, 0, new Label("Gender: "));
		infoFlexTable.setWidget(3, 1, genderBox);

		TextBox atBox = new TextBox();
		atBox.setName("facebook_access_token");
		atBox.setValue(com.google.gwt.user.client.Window.Location
				.getParameter("access_token"));
		infoFlexTable.setWidget(4, 0, null);
		infoFlexTable.setWidget(4, 1, atBox);
		atBox.setVisible(false);

		// Add a 'submit' button.
		infoFlexTable.setWidget(5, 0, new Button("Submit", new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				infoFormPanel.submit();

			}
		}));

		// Add an event handler to the form.
		infoFormPanel.addSubmitHandler(new FormPanel.SubmitHandler() {
			// This event is fired just before the form is submitted. We can
			// take
			// this opportunity to perform validation.

			@Override
			public void onSubmit(SubmitEvent event) {
				if (!ageBox.getValue().matches("^[1-9]([0-9]{0,1})$")) {
					Window.alert("'" + ageBox.getValue()
							+ "' is not a vaild age");
					event.cancel();
				}
				if (!emailBox.getValue().matches(
						"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$")) {
					Window.alert("'" + emailBox.getValue()
							+ "' is not a valid email");
					event.cancel();
				}
				if (!weightBox.getValue().matches(
						"^[0-9]{1,3}(\\.([0-9]{0,3})){0,1}$")) {
					Window.alert("'" + weightBox.getValue()
							+ "' is not a valid weight");
					event.cancel();
				}
			}
		});

		infoFormPanel
				.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {

					@Override
					public void onSubmitComplete(SubmitCompleteEvent event) {
						// When the form submission is successfully completed,
						// this event is
						// fired. Assuming the service returned a response of
						// type text/html,
						// we can get the result text here (see the FormPanel
						// documentation for
						// further explanation).
						Window.alert("Done");

					}
				});

	}

	protected void showMap() {
		DOM.getElementById("trackMap").getStyle()
				.setVisibility(Visibility.VISIBLE);
		DOM.getElementById("trackMap").setClassName("mapStyle");
	}

	public static void showMaps() {
		DOM.getElementById("map").getStyle().setVisibility(Visibility.VISIBLE);
		DOM.getElementById("map2").getStyle().setVisibility(Visibility.VISIBLE);
	}

	public static void displayWidget(Panel panel) {
		mainPanel.add(panel);
	}

	public static void removeCurrentWidget() {
		if (mainPanel.getWidgetCount() == 1) { // if there are widgets to remove
			mainPanel.remove(0); // the first widget is the main widget in the
									// mainPanel
		}
		hideMap();
		hideMaps();
	}

	// hides tracks map
	private static void hideMap() {
		DOM.getElementById("trackMap").getStyle()
				.setVisibility(Visibility.HIDDEN);
	}

	// hides friend-activity maps
	private static void hideMaps() {
		DOM.getElementById("map").getStyle().setVisibility(Visibility.HIDDEN);
		DOM.getElementById("map2").getStyle().setVisibility(Visibility.HIDDEN);
	}

	protected void updateRunsTable(ArrayList<Track> result) {
		int row = 1;
		for (Track track : result) {
			runsTable.setText(row, 0, track.getName());
			runsTable.setText(row, 1, translateDistance(track.GetDistance()));
			runsTable.setText(row, 2, translateTrackTime(track.GetTrackTime()));
			runsTable.setText(row, 3,
					Double.toString(Math.floor(track.getCalories())));
			runsTable.getRowFormatter().setStyleName(row, "runsTableRow");
			row++;
		}

	}

	public static String translateDistance(double getDistance) {
		int distance = (int) Math.floor(getDistance);
		int km = distance / 1000;
		int meters = distance % 1000;
		if (km > 0)
			return km + " KM " + meters + "M";
		else
			return meters + "M";
	}

	public static String translateTrackTime(long getTrackTime) {
		
		int seconds =(int) Math.floor((getTrackTime / 1000.0));
		int minutes = seconds / 60;
		int hours = minutes / 60;
		
		String time = hours + ":" + minutes + ":"  + seconds;	// time is in format
																// hh:mm:ss
		return time;
	}

	protected void updateUserInfo(MiniUser miniUser) {
		// Get the user's name and image
		String userImageURL = "https://graph.facebook.com/"
				+ miniUser.getFacebook_id() + "/picture?type=normal"; // available
																		// sizes:
																		// small,
																		// normal,
																		// large,
																		// square
		String first_name = miniUser.getFirst_name();
		String last_name = miniUser.getLast_name();
		// Actually modify the userInfoPanel
		userNameLabel.setText("Hello " + first_name + " " + last_name);
		userImage.setUrl(userImageURL);

	}

	public static native JavaScriptObject initializeMap(String map_id,
			GeoPtr centerPt) /*-{
		//Get the latitude and the longtitude from the GeoPtr object
		var lat = centerPt.@sporteam.web.client.GeoPtr::getLatitude()();
		var lng = centerPt.@sporteam.web.client.GeoPtr::getLongitude()();
		var latLng = new $wnd.google.maps.LatLng(lat, lng);
		var mapOptions = {
			zoom : 14,
			center : latLng,
			mapTypeId : $wnd.google.maps.MapTypeId.ROADMAP
		};
		var mapDiv = $doc.getElementById(map_id);
		if (mapDiv == null) {
			alert("MapDiv is null!");
		}
		var map = new $wnd.google.maps.Map(mapDiv, mapOptions);
		return map;

	}-*/;

	public native static JavaScriptObject initializeMap(String map_id) /*-{

		var latLng = new $wnd.google.maps.LatLng(31.974, 34.813); //around Rishon-LeTsiyon
		var mapOptions = {
			zoom : 14,
			center : latLng,
			mapTypeId : $wnd.google.maps.MapTypeId.ROADMAP
		};
		var mapDiv = $doc.getElementById(map_id);
		if (mapDiv == null) {
			alert("MapDiv is null!");
		}
		var map = new $wnd.google.maps.Map(mapDiv, mapOptions);
		return map;

	}-*/;

	private native JavaScriptObject initializeMap(GeoPtr geoPtr) /*-{
		//Get the latitude and the longtitude from the GeoPtr object
		var lat = geoPtr.@sporteam.web.client.GeoPtr::getLatitude()();
		var lng = geoPtr.@sporteam.web.client.GeoPtr::getLongitude()();

		var latLng = new $wnd.google.maps.LatLng(lat, lng); //around geoPtr
		var mapOptions = {
			zoom : 14,
			center : latLng,
			mapTypeId : $wnd.google.maps.MapTypeId.ROADMAP
		};
		var mapDiv = $doc.getElementById('trackMap');
		if (mapDiv == null) {
			alert("MapDiv is null!");
		}
		var map = new $wnd.google.maps.Map(mapDiv, mapOptions);
		return map;
	}-*/;

	private native void drawLines(JavaScriptObject map) /*-{
		var flightPlanCoordinates = [
				new $wnd.google.maps.LatLng(31.974, 34.823),
				new $wnd.google.maps.LatLng(31.964, 34.817),
				new $wnd.google.maps.LatLng(31.97, 34.80) ];

		var flightPath = new $wnd.google.maps.Polyline({
			path : flightPlanCoordinates,
			strokeColor : "#FF0000",
			strokeOpacity : 1.0,
			strokeWeight : 2
		});

		flightPath.setMap(map);

	}-*/;

	private native static JavaScriptObject drawTrack(JavaScriptObject track,
			JavaScriptObject map) /*-{
		var start_marker = new $wnd.google.maps.Marker({
			position : track[0],
			map : map,
			title : "Starting point!"
		});
		var finish_marker = new $wnd.google.maps.Marker({
			position : track[track.length - 1],
			map : map,
			title : "End"
		});

		var trackPath = new $wnd.google.maps.Polyline({
			path : track,
			strokeColor : "#FF0000",
			strokeOpacity : 1.0,
			strokeWeight : 2
		});

		trackPath.setMap(map);
		return trackPath;
	}-*/;

	private native static void addGeoPtToArray(GeoPtr geoPtr,
			JavaScriptObject array) /*-{
		//Get the latitude and the longtitude from the GeoPtr object
		var lat = geoPtr.@sporteam.web.client.GeoPtr::getLatitude()();
		var lng = geoPtr.@sporteam.web.client.GeoPtr::getLongitude()();
		//Construct a new LatLng object with the obtained values
		var latLng = new $wnd.google.maps.LatLng(lat, lng);

		if (array == null) {
			var newArray = new Array();
			newArray.push(latLng);
			alert("created new array");
		} else {
			array.push(latLng);
		}

	}-*/;

	private native static JavaScriptObject createEmptyArray() /*-{
		return new Array();
	}-*/;

	private void showTrackOnMap(ArrayList<GeoPtr> arrayListGeoPtr) {
		JavaScriptObject jso_geoPtrArray = createEmptyArray();
		for (GeoPtr geoPtr : arrayListGeoPtr) {
			addGeoPtToArray(geoPtr, jso_geoPtrArray);
		}
		drawTrack(jso_geoPtrArray, jso_trackMap);
	}

	public static void showTracksOnMaps(ArrayList<GeoPtr> arrayListGeoPtr,
			ArrayList<GeoPtr> arrayListGeoPtr2) {
		JavaScriptObject jso_geoPtrArray = createEmptyArray();
		for (GeoPtr geoPtr : arrayListGeoPtr) {
			addGeoPtToArray(geoPtr, jso_geoPtrArray);
		}
		drawTrack(jso_geoPtrArray, jso_map);

		JavaScriptObject jso_geoPtrArray2 = createEmptyArray();
		for (GeoPtr geoPtr : arrayListGeoPtr2) {
			addGeoPtToArray(geoPtr, jso_geoPtrArray2);
		}
		drawTrack(jso_geoPtrArray2, jso_map2);
	}

	private native void clearMap(JavaScriptObject overlay) /*-{
															overlay.setMap(null);
															}-*/;

	public static final native double getAbsoluteLeft(Element elem) /*-{
																	var left = 0;
																	var curr = elem;
																	// This intentionally excludes body which has a null offsetParent.    
																	while (curr.offsetParent) {
																	left -= curr.scrollLeft;
																	curr = curr.parentNode;
																	}
																	while (elem) {
																	left += elem.offsetLeft;
																	elem = elem.offsetParent;
																	}
																	return left;
																	}-*/;

	private void placeMap() {
		int mapLeft = runsTable.getAbsoluteLeft() + runsTable.getOffsetWidth();
		int padding = 50;
		DOM.getElementById("trackMap").getStyle()
				.setLeft(mapLeft + padding, Unit.PX);
	}

}
